package com.hyt.it.ogt.pj.data.service.pj.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.it.ogt.pj.data.common.ResponseCode;
import com.hyt.it.ogt.pj.data.enums.AutoFlagEnums;
import com.hyt.it.ogt.pj.data.enums.CommonEnums;
import com.hyt.it.ogt.pj.data.enums.MarkTypeEnums;
import com.hyt.it.ogt.pj.data.enums.MarkmodelEnums;
import com.hyt.it.ogt.pj.data.mapper.pj.ProjectMapper;
import com.hyt.it.ogt.pj.data.mapper.pj.ProjectSettingMapper;
import com.hyt.it.ogt.pj.data.mapper.pj.SubjectScoreMapper;
import com.hyt.it.ogt.pj.data.mapper.pj.TaskMapper;
import com.hyt.it.ogt.pj.data.model.dto.ExamExpertSettingParam;
import com.hyt.it.ogt.pj.data.model.entity.pj.ExamExpert;
import com.hyt.it.ogt.pj.data.model.entity.pj.ModeExpert;
import com.hyt.it.ogt.pj.data.model.entity.pj.PieceScore;
import com.hyt.it.ogt.pj.data.model.entity.pj.Project;
import com.hyt.it.ogt.pj.data.model.entity.pj.ProjectSetting;
import com.hyt.it.ogt.pj.data.model.entity.pj.Task;
import com.hyt.it.ogt.pj.data.model.entity.pj.TeacherTaskInfo;
import com.hyt.it.ogt.pj.data.model.vo.pj.ModeExamExpertVo;
import com.hyt.it.ogt.pj.data.model.vo.pj.SubjectScore;
import com.hyt.it.ogt.pj.data.model.vo.pj.TaskNumberVo;
import com.hyt.it.ogt.pj.data.service.pj.ICommonAutomaticAllocationService;
import com.hyt.it.ogt.pj.data.service.pj.IExamExpertService;
import com.hyt.it.ogt.pj.data.service.pj.IModeExpertService;
import com.hyt.it.ogt.pj.data.service.pj.IPieceScoreService;
import com.hyt.it.ogt.pj.data.service.pj.ITeacherTaskInfoService;

/**
 * <p>
 * 评卷项目配置 服务实现类
 * </p>
 *
 * @author liy
 * @since 2022-02-28
 */
@Service
public class CommonAutomaticAllocationServiceImpl extends BaseServiceImpl<ProjectSettingMapper, ProjectSetting> implements ICommonAutomaticAllocationService {
	protected Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private ProjectSettingMapper projectSettingMapper;

	@Autowired
	private ProjectMapper projectMapper;

	@Autowired
	private TaskMapper taskMapper;

	@Autowired
	private IModeExpertService modeExpertService;

	@Autowired
	private IExamExpertService examExpertService;

	@Autowired
	private ITeacherTaskInfoService teacherTaskInfoService;

	@Autowired
	private IPieceScoreService pieceScoreService;

	@Autowired
	private SubjectScoreMapper subjectScoreMapper;

	@Resource
	RedisTemplate<String, String> redisTemplate;

	@Override
	public Integer commonAutomaticAllocation(String projectId) {
		// 查询评卷项目
		Project project = projectMapper.selectById(projectId);
		if (null == project) {
			return ResponseCode.MARK_PROJECT_NOT_EMPTY;
		}

		// 如果评卷已经发布，则不做分配
		if (null != project.getMarkPublish() && !CommonEnums.TASK_PUBLISH_STATUS_1.getCode().equals(project.getMarkPublish())) {
			return ResponseCode.PUBLISH_TASK_NOT_SETTING;
		}

		// 获取评卷规则
		ProjectSetting projectSetting = projectSettingMapper.getProjectSettingByProjectId(projectId);
		if (null == projectSetting) {
			return ResponseCode.PROJECT_SETTING_NOT_EMPTY;
		}

		String markModel = projectSetting.getMarkModel();
		// 获取评卷模式
		QueryWrapper<ModeExpert> modeExpertWrapper = new QueryWrapper<ModeExpert>();
		modeExpertWrapper.lambda().eq(ModeExpert::getProjectId, projectId);
		List<ModeExpert> modeExperts = modeExpertService.list(modeExpertWrapper);
		if (CollectionUtils.isEmpty(modeExperts)) {
			return ResponseCode.MARK_MODEL_NOT_EMPRY;
		}
		// 自动分配开关开启才会自动分配任务
		if (!AutoFlagEnums.AUTO_FlAG_OPEN.getCode().equals(modeExperts.get(0).getAutoFlag())) {
			return ResponseCode.SUCCESS;
		}
		// 评卷专家
		List<ModeExamExpertVo> modeExamExpertVos = getModeExamExpertVos(projectId, project.getExamClassfication(), markModel);
		if (CollectionUtils.isEmpty(modeExamExpertVos)) {
			return ResponseCode.EXAM_EXPERT_IS_EMPTY;
		}
		// 设置的专家评卷数
		Map<String, Integer> numerMap = getNumberMap(markModel, modeExamExpertVos);
		if (CollectionUtils.isEmpty(numerMap)) {
			return ResponseCode.MARK_MODEL_NOT_EMPRY;
		}
		// 分组评卷专家模式
		Map<String, List<ModeExamExpertVo>> examExpertMap = bulidExamExpertMap(markModel, modeExamExpertVos);
		if (CollectionUtils.isEmpty(examExpertMap)) {
			return ResponseCode.EXAM_EXPERT_IS_EMPTY;
		}

		// 分组未评卷考生任务
		ExamExpertSettingParam examExpertSettingParam = new ExamExpertSettingParam();
		examExpertSettingParam.setProjectId(projectId);
		Map<String, List<Task>> tasksMap = buildTaskMap(markModel, examExpertSettingParam);
		if (CollectionUtils.isEmpty(tasksMap)) {
			return ResponseCode.SUCCESS;
		}
		// 评卷专家
		QueryWrapper<ExamExpert> examExpertWrapper = new QueryWrapper<>();
		examExpertWrapper.lambda().eq(ExamExpert::getProjectId, projectId);
		List<ExamExpert> experts = examExpertService.list(examExpertWrapper);
		if (CollectionUtils.isEmpty(experts)) {
			return ResponseCode.EXAM_EXPERT_IS_EMPTY;
		}

		// 客观题得分
		Map<String, SubjectScore> subjectScoreMap = bulidSubjectScoreMap(projectId);

		// 开启自动分配第一次评卷quantity为0，后面再用quantity+size
		// 封装所以已经分配的任务数
		Map<String, List<TaskNumberVo>> quantityMap = getQuantityMap(projectId);
		Map<String, ExamExpert> expertMap = experts.stream().collect(Collectors.toMap(ExamExpert::getId, ExamExpert -> ExamExpert, (key1, key2) -> key2));
		List<TeacherTaskInfo> teacherTaskInfos = new ArrayList<>();
		// 开始分配任务，tasksMap为需要分配的任务
		for (Map.Entry<String, List<Task>> entry : tasksMap.entrySet()) {
			if (CollectionUtils.isEmpty(examExpertMap.get(entry.getKey()))) {
				continue;
			}
			Set<String> pieceIds = entry.getValue().stream().filter(e -> StringUtils.isNotEmpty(e.getPieceId())).map(e -> e.getPieceId()).collect(Collectors.toSet());
			// 获取分组的专家
			List<ModeExamExpertVo> examExpertVos = examExpertMap.get(entry.getKey());
			// 流水评卷
			if (MarkTypeEnums.MARK_TYPE_FLOW.getCode().equals(projectSetting.getMarkType())) {
				// 自动分配
				if (AutoFlagEnums.AUTO_FlAG_OPEN.getCode().equals(examExpertVos.get(0).getAutoFlag())) {
					flowingAutoCalculationRule(examExpertVos, entry.getValue(), expertMap, subjectScoreMap);
				} else {
					flowingCalculationRule(examExpertVos, entry.getValue(), quantityMap, subjectScoreMap, markModel);
				}
			} else if (MarkTypeEnums.MARK_TYPE_CROSS.getCode().equals(projectSetting.getMarkType())) {
				// 自动分配
				if (AutoFlagEnums.AUTO_FlAG_OPEN.getCode().equals(examExpertVos.get(0).getAutoFlag())) {
					crossAutoCalculationRule(examExpertVos, entry.getValue(), numerMap.get(entry.getKey()), expertMap, quantityMap, subjectScoreMap, markModel);
				} else {
					crossCalculationRule(examExpertVos, entry.getValue(), quantityMap, numerMap.get(entry.getKey()), subjectScoreMap, markModel);
				}
			}
			for (ModeExamExpertVo modeExamExpertVo : examExpertVos) {
				for (String pieceId : pieceIds) {
					teacherTaskInfos.add(buildTeacherTaskInfo(modeExamExpertVo.getExpertId(), pieceId, projectId, modeExamExpertVo.getSubjectId(), modeExamExpertVo.getBatchId(),
							modeExamExpertVo.getPlaceId(), modeExamExpertVo.getRoomId()));
				}
			}
		}
		dealTeacherTaskInfo(teacherTaskInfos, projectId);
		return ResponseCode.SUCCESS;
	}

	private List<ModeExamExpertVo> getModeExamExpertVos(String projectId, Integer examClassfication, String markModel) {

		if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(markModel)) {
			return examExpertService.queryEaxmModeExamExpertVos(projectId, markModel, null, null);
		} else if (MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(markModel)) {
			return examExpertService.queryEaxmModeExamExpertVos(projectId, markModel, markModel, null);
		} else if (MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(markModel)) {
			return examExpertService.queryEaxmModeExamExpertVos(projectId, markModel, markModel, markModel);
		} else {
			return examExpertService.queryExamExpertVos(projectId);
		}

	}

	private Map<String, Integer> getNumberMap(String markModel, List<ModeExamExpertVo> modeExperts) {
		Map<String, Integer> numerMap = new HashMap<>();
		if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(markModel)) {
			numerMap = modeExperts.stream().filter(e -> StringUtils.isNotEmpty(e.getSubjectId())).collect(Collectors.toMap(e -> e.getSubjectId(), ModeExamExpertVo::getNumber, (key1, key2) -> key2));

		}
		if (MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(markModel)) {
			numerMap = modeExperts.stream().filter(e -> StringUtils.isNotEmpty(e.getBatchId())).collect(Collectors.toMap(e -> e.getBatchId(), ModeExamExpertVo::getNumber, (key1, key2) -> key2));

		}
		if (MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(markModel)) {
			numerMap = modeExperts.stream().filter(e -> StringUtils.isNotEmpty(e.getRoomId())).collect(Collectors.toMap(e -> e.getRoomId(), ModeExamExpertVo::getNumber, (key1, key2) -> key2));

		}
		return numerMap;
	}

	private Map<String, List<TaskNumberVo>> getQuantityMap(String projectId) {
		List<TaskNumberVo> taskNumberVos = taskMapper.queryTaskNumberVo(projectId);
		Map<String, List<TaskNumberVo>> quantityMap = taskNumberVos.stream().collect(Collectors.groupingBy(t -> t.getExpertId()));
		return quantityMap;
	}

	private Map<String, SubjectScore> bulidSubjectScoreMap(String projectId) {
		QueryWrapper<SubjectScore> subjectScoreWrapper = new QueryWrapper<>();
		subjectScoreWrapper.lambda().eq(SubjectScore::getProjectId, projectId);
		List<SubjectScore> subjectScores = subjectScoreMapper.selectList(subjectScoreWrapper);
		return subjectScores.stream().collect(Collectors.toMap(s -> s.getSubjectId() + s.getEncodeId(), SubjectScore -> SubjectScore, (key1, key2) -> key2));
	}

	private void dealTeacherTaskInfo(List<TeacherTaskInfo> teacherTaskInfos, String projectId) {
		Set<String> pieceCodes = teacherTaskInfos.stream().filter(e -> StringUtils.isNotEmpty(e.getPieceCode())).map(e -> e.getPieceCode()).collect(Collectors.toSet());
		QueryWrapper<TeacherTaskInfo> teacherTaskInfoWrapper = new QueryWrapper<>();
		teacherTaskInfoWrapper.lambda().eq(TeacherTaskInfo::getProjectId, projectId).in(TeacherTaskInfo::getPieceCode, pieceCodes);
		// 查询出已经存在的任务
		List<TeacherTaskInfo> alreadyTeacherTaskInfos = teacherTaskInfoService.list(teacherTaskInfoWrapper);
		Map<String, String> teacherTaskInfoMap = alreadyTeacherTaskInfos.stream()
				.collect(Collectors.toMap(e -> e.getPieceCode() + e.getSubjectId() + e.getBatchId() + e.getPlaceId() + e.getRoomId() + e.getUserId(), TeacherTaskInfo::getId, (key1, key2) -> key2));
		List<TeacherTaskInfo> addTeacherTaskInfos = new ArrayList<>();
		// 过滤掉已经存在的任务
		for (TeacherTaskInfo teacherTaskInfo : teacherTaskInfos) {
			if (!CollectionUtils.isEmpty(teacherTaskInfoMap) && null != teacherTaskInfoMap.get(teacherTaskInfo.getPieceCode() + teacherTaskInfo.getSubjectId() + teacherTaskInfo.getBatchId()
					+ teacherTaskInfo.getPlaceId() + teacherTaskInfo.getRoomId() + teacherTaskInfo.getUserId())) {
				continue;
			}
			addTeacherTaskInfos.add(teacherTaskInfo);
		}
		if (!CollectionUtils.isEmpty(addTeacherTaskInfos)) {
			teacherTaskInfoService.saveBatch(addTeacherTaskInfos);
		}
	}

	private Map<String, List<Task>> buildTaskMap(String markModel, ExamExpertSettingParam examExpertSettingParam) {
		// 如果自动分配标识打开且还有考生任务则重新平均给专家分配任务，变更专家的评卷数
		// 找出未分配考生
		// 找出任务
		List<Task> tasksList = taskMapper.queryTaskByExamExpertSetting(examExpertSettingParam);
		if (CollectionUtils.isEmpty(tasksList)) {
			return null;
		}
		Map<String, List<Task>> tasksMap = null;
		if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(markModel)) {
			tasksMap = tasksList.stream().filter(e -> StringUtils.isNotEmpty(e.getSubjectId())).collect(Collectors.groupingBy(c -> c.getSubjectId()));

		}
		if (MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(markModel)) {
			tasksMap = tasksList.stream().filter(e -> StringUtils.isNotEmpty(e.getBatchId())).collect(Collectors.groupingBy(c -> c.getBatchId()));

		}
		if (MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(markModel)) {
			tasksMap = tasksList.stream().filter(e -> StringUtils.isNotEmpty(e.getRoomId())).collect(Collectors.groupingBy(c -> c.getRoomId()));

		}
		return tasksMap;
	}

	/**
	 * 封装专家map
	 *
	 * @param markModel
	 * @return
	 */
	private Map<String, List<ModeExamExpertVo>> bulidExamExpertMap(String markModel, List<ModeExamExpertVo> modeExamExpertVos) {

		Map<String, List<ModeExamExpertVo>> examExpertMap = new HashMap<>();
		if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(markModel)) {
			examExpertMap = modeExamExpertVos.stream().filter(e -> StringUtils.isNotEmpty(e.getSubjectId())).collect(Collectors.groupingBy(c -> c.getSubjectId()));
		}
		if (MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(markModel)) {
			examExpertMap = modeExamExpertVos.stream().filter(e -> StringUtils.isNotEmpty(e.getBatchId())).collect(Collectors.groupingBy(c -> c.getBatchId()));
		}
		if (MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(markModel)) {
			examExpertMap = modeExamExpertVos.stream().filter(e -> StringUtils.isNotEmpty(e.getRoomId())).collect(Collectors.groupingBy(c -> c.getRoomId()));

		}
		return examExpertMap;
	}

	/**
	 * 交叉评卷分配专家任务规则
	 *
	 * @param tasks
	 * @param examExpertVos
	 * @param
	 *
	 */
	private void crossCalculationRule(List<ModeExamExpertVo> examExpertVos, List<Task> tasks, Map<String, List<TaskNumberVo>> quantityMap, Integer number, Map<String, SubjectScore> subjectScoreMap,
			String markModel) {

		List<PieceScore> pieceScores = new ArrayList<>();
		List<Task> allTasks = new ArrayList<>();
		// 将能看最多任务的老师排在前面
		examExpertVos.sort(Comparator.comparing(ModeExamExpertVo::getQuantity).reversed());
		// 需要分配的总任务数
		for (int i = 0; i < number; i++) {
			allTasks.addAll(tasks);
		}
		for (ModeExamExpertVo examExpert : examExpertVos) {
			// 查询出专家已经评卷的多少份，用设置的Quantity减去已经评卷的数量
			if (!CollectionUtils.isEmpty(quantityMap) && !CollectionUtils.isEmpty(quantityMap.get(examExpert.getExpertId())) && null != examExpert.getQuantity()) {
				// quantityMap统计是project专家的总已评卷数，未区分考场和科目。存在project多考场or多科目分配给同一个专家
				int quantity = getQuantity(quantityMap.get(examExpert.getExpertId()), examExpert, markModel);
				examExpert.setQuantity(examExpert.getQuantity().intValue() - quantity);
			}
			Map<String, String> countMap = new HashMap<>();
			Iterator<Task> iterator = allTasks.iterator();
			while (iterator.hasNext()) {
				// 老师的评卷数量已经全部分配
				if (examExpert.getQuantity().intValue() == 0) {
					break;
				}
				Task task = iterator.next();
				// 如果给当前专家已经分配了改任务，则不重复分配
				if (StringUtils.isNotEmpty(countMap.get(task.getId()))) {
					continue;
				}
				// 专家已经评卷了当前任务则不再重复分配给改专家
				if (!CollectionUtils.isEmpty(quantityMap) && !CollectionUtils.isEmpty(quantityMap.get(examExpert.getExpertId()))) {
					Set<String> taskIds = quantityMap.get(examExpert.getExpertId()).stream().map(t -> t.getTaskId()).collect(Collectors.toSet());
					if (taskIds.contains(task.getId())) {
						continue;
					}
				}
				pieceScores.add(buildPieceScores(examExpert.getExpertId(), task, subjectScoreMap));
				countMap.put(task.getId(), task.getId());
				iterator.remove();
				// 分配好一个则将examExpert.getQuantity() - 1
				examExpert.setQuantity(examExpert.getQuantity() - 1);
			}
		}
		if(!CollectionUtils.isEmpty(pieceScores)) {
			pieceScoreService.saveBatch(pieceScores);
		}
	}

	/**
	 * 交叉评卷自动分配专家任务规则
	 *
	 * @param
	 * @param examExpertVos
	 * @param
	 *
	 */
	private void crossAutoCalculationRule(List<ModeExamExpertVo> examExpertVos, List<Task> tasks, Integer number, Map<String, ExamExpert> expertMap, Map<String, List<TaskNumberVo>> quantityMap,
			Map<String, SubjectScore> subjectScoreMap, String markModel) {
		// 每个老师的评卷任务
		List<PieceScore> pieceScores = new ArrayList<>();
		// 将能看最多任务的老师排在前面
		examExpertVos.sort(Comparator.comparing(ModeExamExpertVo::getQuantity).reversed());
		for (Task task : tasks) {
			int count = 0;
			for (ModeExamExpertVo modeExamExpertVo : examExpertVos) {
				// 专家已经评卷了当前任务则不再重复分配给改专家
				if (!CollectionUtils.isEmpty(quantityMap) && !CollectionUtils.isEmpty(quantityMap.get(modeExamExpertVo.getExpertId()))) {
					// quantityMap统计是project专家的总已评卷数，未区分考场和科目。存在project多考场or多科目分配给同一个专家
					int quantity = getQuantity(quantityMap.get(modeExamExpertVo.getExpertId()), modeExamExpertVo, markModel);
					if (quantity > 0) {
						Set<String> taskIds = quantityMap.get(modeExamExpertVo.getExpertId()).stream().map(t -> t.getTaskId()).collect(Collectors.toSet());
						if (taskIds.contains(task.getId())) {
							continue;
						}
					}
				}
				// 当前任务的分配次数大于评卷设置的评卷次数
				if (count >= number) {
					break;
				}
				pieceScores.add(buildPieceScores(modeExamExpertVo.getExpertId(), task, subjectScoreMap));
				count++;
			}
		}

		// 重新计算专家的评卷数
		Map<String, List<PieceScore>> pieceScoreMap = pieceScores.stream().collect(Collectors.groupingBy(c -> c.getUserId()));
		List<ExamExpert> examExperts = new ArrayList<>();
		for (ModeExamExpertVo modeExamExpertVo : examExpertVos) {
			if (CollectionUtils.isEmpty(pieceScoreMap) || CollectionUtils.isEmpty(pieceScoreMap.get(modeExamExpertVo.getExpertId()))) {
				continue;
			}
			if (CollectionUtils.isEmpty(expertMap) || null == expertMap.get(modeExamExpertVo.getId())) {
				continue;
			}
			ExamExpert examExpert = expertMap.get(modeExamExpertVo.getId());
			if (CollectionUtils.isEmpty(quantityMap) || CollectionUtils.isEmpty(quantityMap.get(examExpert.getExpertId())) || quantityMap.get(examExpert.getExpertId()).size() == 0) {
				examExpert.setQuantity(pieceScoreMap.get(examExpert.getExpertId()).size());
			} else {
				examExpert.setQuantity(examExpert.getQuantity() + pieceScoreMap.get(examExpert.getExpertId()).size());

			}
			examExperts.add(examExpert);

		}
		if(!CollectionUtils.isEmpty(pieceScores)) {
			pieceScoreService.saveBatch(pieceScores);
		}
		if(!CollectionUtils.isEmpty(examExperts)) {
			examExpertService.updateBatchById(examExperts);
		}

	}

	/**
	 * 流水评卷分配专家任务规则
	 *
	 * @param
	 * @param examExpertVos
	 * @param
	 *
	 */
	private void flowingCalculationRule(List<ModeExamExpertVo> examExpertVos, List<Task> tasks, Map<String, List<TaskNumberVo>> quantityMap, Map<String, SubjectScore> subjectScoreMap,
			String markModel) {
		List<PieceScore> pieceScores = new ArrayList<>(tasks.size());
		// 将能看最多任务的老师排在前面
		examExpertVos.sort(Comparator.comparing(ModeExamExpertVo::getQuantity).reversed());
		for (ModeExamExpertVo examExpert : examExpertVos) {
			// 查询出专家已经评卷的多少份，用设置的Quantity减去已经评卷的数量
			if (!CollectionUtils.isEmpty(quantityMap) && !CollectionUtils.isEmpty(quantityMap.get(examExpert.getExpertId()))) {
				// quantityMap统计是project专家的总已评卷数，未区分考场和科目。存在project多考场or多科目分配给同一个专家
				// int quantity =
				// quantityMap.get(examExpert.getExpertId()).size();
				int quantity = getQuantity(quantityMap.get(examExpert.getExpertId()), examExpert, markModel);
				examExpert.setQuantity(examExpert.getQuantity().intValue() - quantity);
			}
			// 总任务
			Iterator<Task> iterator = tasks.iterator();
			while (iterator.hasNext()) {
				// 老师的评卷数量已经全部分配
				if (examExpert.getQuantity().intValue() == 0) {
					break;
				}
				Task task = iterator.next();
				pieceScores.add(buildPieceScores(examExpert.getExpertId(), task, subjectScoreMap));
				iterator.remove();
				// 分配好一个则将examExpert.getQuantity() - 1
				examExpert.setQuantity(examExpert.getQuantity() - 1);
			}
		}
		if(!CollectionUtils.isEmpty(pieceScores)) {
			pieceScoreService.saveBatch(pieceScores);
		}

	}

	private int getQuantity(List<TaskNumberVo> taskNumberVos, ModeExamExpertVo examExpert, String markModel) {
		int quantity = 0;
		if (MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(markModel)) {
			for (TaskNumberVo taskNumberVo : taskNumberVos) {
				if (examExpert.getExpertId().equals(taskNumberVo.getExpertId()) && examExpert.getSubjectId().equals(taskNumberVo.getSubjectId())) {
					quantity++;
				}
			}
		}
		if (MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(markModel)) {
			for (TaskNumberVo taskNumberVo : taskNumberVos) {
				if (examExpert.getExpertId().equals(taskNumberVo.getExpertId()) && examExpert.getBatchId().equals(taskNumberVo.getBatchId())) {
					quantity++;
				}
			}
		}
		if (MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(markModel)) {
			for (TaskNumberVo taskNumberVo : taskNumberVos) {
				if (examExpert.getExpertId().equals(taskNumberVo.getExpertId()) && examExpert.getRoomId().equals(taskNumberVo.getRoomId())) {
					quantity++;
				}
			}
		}
		return quantity;
	}

	/**
	 * 流水评卷自动分配专家任务规则
	 *
	 * @param
	 * @param modeExamExpertVos
	 * @param
	 *
	 */
	private void flowingAutoCalculationRule(List<ModeExamExpertVo> modeExamExpertVos, List<Task> tasks, Map<String, ExamExpert> expertMap, Map<String, SubjectScore> subjectScoreMap) {
		List<PieceScore> pieceScores = new ArrayList<>();
		// 平均分配的评卷任务都是一个一个的推送过来的
		// 将能看最多任务的专家排在前面
		modeExamExpertVos.sort(Comparator.comparing(ModeExamExpertVo::getQuantity).reversed());
		for (Task task : tasks) {
			//查询当前专家是否对数据已经分配
			String expertId = modeExamExpertVos.get(0).getExpertId();
			PieceScore pieceScore = pieceScoreService.selectPieceScoreBySubjectIdAndTaskIdAndEncodeIdAndUserId(task.getSubjectId(), task.getPieceId(), task.getId(), task.getEncodeId(), expertId);
			if(null == pieceScore) {
				// 专家已经评卷了当前任务则不再重复分配给改专家
				pieceScores.add(buildPieceScores(modeExamExpertVos.get(0).getExpertId(), task, subjectScoreMap));
			}
		}
		// 更新专家的评卷数
		modeExamExpertVos.get(0).setQuantity(modeExamExpertVos.get(0).getQuantity() + 1);

		// 重新计算专家的评卷数
		List<ExamExpert> examExperts = new ArrayList<>();
		for (ModeExamExpertVo modeExamExpertVo : modeExamExpertVos) {
			if (CollectionUtils.isEmpty(expertMap) || null == expertMap.get(modeExamExpertVo.getId())) {
				continue;
			}
			ExamExpert examExpert = expertMap.get(modeExamExpertVo.getId());
			examExpert.setQuantity(modeExamExpertVo.getQuantity());
			examExperts.add(examExpert);
		}
		if(!CollectionUtils.isEmpty(examExperts)) {
			examExpertService.updateBatchById(examExperts);
		}
		if(!CollectionUtils.isEmpty(pieceScores)) {
			pieceScoreService.saveBatch(pieceScores);
		}
	}

	private PieceScore buildPieceScores(String expertId, Task task, Map<String, SubjectScore> subjectScoreMap) {
		PieceScore pieceScore = new PieceScore();
		pieceScore.setEncodeId(task.getEncodeId());
		pieceScore.setPieceId(task.getPieceId());
		pieceScore.setTaskId(task.getId());
		pieceScore.setSubjectId(task.getSubjectId());

		if (!CollectionUtils.isEmpty(subjectScoreMap) && StringUtils.isNotEmpty(pieceScore.getSubjectId()) && null != subjectScoreMap.get(pieceScore.getSubjectId() + task.getEncodeId())) {
			pieceScore.setObjectiveScore(subjectScoreMap.get(pieceScore.getSubjectId() + task.getEncodeId()).getObjectiveScore());
		}

		pieceScore.setFinish(CommonEnums.TASK_MARK_STATUS_0.getCode());
		pieceScore.setMarkTimes(CommonEnums.Mark_Status_0.getCode());
		pieceScore.setUserId(expertId);
		pieceScore.setCreateBy("");
		pieceScore.setCreateDate(LocalDateTime.now());
		pieceScore.setUpdateBy("");
		pieceScore.setUpdateDate(LocalDateTime.now());
		return pieceScore;
	}

	private TeacherTaskInfo buildTeacherTaskInfo(String expertId, String pieceId, String projectId, String subjectId, String batchId, String placeId, String roomId) {
		TeacherTaskInfo teacherTaskInfo = new TeacherTaskInfo();
		teacherTaskInfo.setProjectId(projectId);
		teacherTaskInfo.setSubjectId(subjectId);
		teacherTaskInfo.setPieceCode(pieceId);
		teacherTaskInfo.setUserId(expertId);
		teacherTaskInfo.setBatchId(batchId);
		teacherTaskInfo.setPlaceId(placeId);
		teacherTaskInfo.setRoomId(roomId);
		teacherTaskInfo.setCreateBy("");
		teacherTaskInfo.setCreateDate(LocalDateTime.now());
		teacherTaskInfo.setUpdateBy("");
		teacherTaskInfo.setUpdateDate(LocalDateTime.now());
		return teacherTaskInfo;
	}

}
